<?php

namespace lico\Tool;

class Captcha
{

    protected $type = 'digit'; //digit,character,arithmetic,chinese

    protected $handler;

    protected $config = [
        'code' => '',
        'length' => '4',
        'imageType' => 'gif', //png,gif,jpeg
        'width' => '150',
        'height' => '50',
        // 'fontFile'=>__DIR__.DS.'Captcha'.DS.'font'.DS.'open_sans.ttf',
        'fontFile' => '',
        'fontSize' => 5, //字体大小
        'groundColor' => ['r' => 255, 'g' => 255, 'b' => 255],
        'spotCount' => '15',
        'spotSize' => 10, //干扰点字体大小,提供：1,2,3,4,5
        // 'spotColor'=>['r'=>255,'g'=>255,'b'=>255],
    ];

    public function __construct($type = '', $length = '')
    {
        $type && $this->setType($type);
        $type = ucfirst(strtolower($this->type));
        $namespace = __CLASS__ . '\\' . $type;
        $this->handler = new $namespace($this->config);
        if ($length) {
            $this->config['length'] = $length;
            $this->config['code'] = $this->handler->getCode($length);
        }
    }

    /**
     * 设置验证码方式
     */
    public function setType($type)
    {
        $this->type = $type;
        return $this->type;
    }

    /**
     * 获取验证码类
     */
    public function getHandler()
    {
        return $this->handler;
    }

    /**
     * 获取验证码
     */
    public function getCode()
    {
        return $this->config['code'];
    }

    public function draw()
    {

        ob_clean(); //清除缓存

        $config = $this->config;

        //创建一张图像
        $image = imagecreatetruecolor($config['width'], $config['height']);

        //为$image设置背景颜色为白色
        $bgcolor = imagecolorallocate($image, $config['groundColor']['r'], $config['groundColor']['g'], $config['groundColor']['b']);

        //填充背景颜色(矩形填充)
        imagefilledrectangle($image, 0, $config['height'], $config['width'], 0, $bgcolor);

        //是否使用字体
        $fontExists = false;
        $config['fontFile'] && file_exists($config['fontFile']) && $fontExists = true;

        //干扰点
        $spot = $this->handler->getSpot($config['spotCount']);
        $spotcontent = '';
        for ($i = 0; $i < $config['spotCount']; $i++) {
            $color = imagecolorallocate($image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(200, 255));
            $spotcontent = mb_substr($spot, $i, 1, 'utf-8'); //防中文乱码
            $x = mt_rand(0, $config['width']);
            $y = mt_rand(0, $config['height']);
            if ($fontExists) {
                $spotSize = $config['spotSize'] < 5 ? 5 : $config['spotSize'];
                imagettftext($image, $spotSize, 0, $x, $y, $color, $config['fontFile'], $spotcontent);
            } else {
                imagestring($image, $config['spotSize'], $x, $y, $spotcontent, $color);
            }
        }

        //获取验证码字符
        $this->config['code'] = $this->handler->getCode($config['length']);
        //字符编码转换
        $oldCoding = mb_detect_encoding($this->config['code'], ['ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5']);
        if ($oldCoding != 'UTF-8') {
            // $this->config['code'] = @iconv($oldCoding,"utf-8//IGNORE",$this->config['code']);
            $this->config['code'] = mb_convert_encoding($this->config['code'], "UTF-8", $oldCoding);
        }
        $len = mb_strlen($this->config['code'], 'utf8');
        $imageWidthGap = $config['width'] / $len; //字体间隔

        //绘字符
        $fontcontent = '';
        for ($i = 0; $i < $len; $i++) {
            $fontcolor = imagecolorallocate($image, mt_rand(0, 156), mt_rand(0, 156), mt_rand(0, 156));
            $fontcontent = mb_substr($this->config['code'], $i, 1, 'utf-8'); //防中文乱码
            //当有字体文件
            if ($fontExists) {
                $fontBox = imagettfbbox($config['fontSize'], 0, $config['fontFile'], $this->config['code'][$i]);
                $min_y = min([$fontBox[1], $fontBox[3], $fontBox[5], $fontBox[7]]);
                $max_y = max([$fontBox[1], $fontBox[3], $fontBox[5], $fontBox[7]]);
                $fontHeight = $max_y - $min_y;
                $fontHeight = $fontHeight < $config['fontSize'] ? $config['fontSize'] : $fontHeight;

                $min_x = min([$fontBox[0], $fontBox[2], $fontBox[4], $fontBox[6]]);
                $max_x = max([$fontBox[0], $fontBox[2], $fontBox[4], $fontBox[6]]);
                $fontWidth = $max_x - $min_x;
                $fontWidth = $fontWidth < $config['fontSize'] ? $config['fontSize'] : $fontWidth;

                //坐标
                $gap = $i + 1;
                $x = mt_rand($imageWidthGap * $i, ($imageWidthGap * $gap - $fontWidth));
                $y = mt_rand($fontHeight, $config['height']);

                imagettftext($image, $config['fontSize'], 0, $x, $y, $fontcolor, $config['fontFile'], $fontcontent);
            } else {
                $fontHeight = imagefontheight($config['fontSize']);
                $fontWidth = imagefontwidth($config['fontSize']);

                //坐标
                $gap = $i + 1;
                $x = mt_rand($imageWidthGap * $i, ($imageWidthGap * $gap - $fontWidth));
                $y = mt_rand(0, $config['height'] - $fontHeight);

                imagestring($image, $config['fontSize'], $x, $y, $fontcontent, $fontcolor);
            }
        }

        header('Content-type:image/' . $config['imageType']);
        $imgFun = 'image' . $config['imageType'];
        call_user_func($imgFun, $image);
        imagedestroy($image);
    }
}
